#include <iostream>
#include <vector>
#include <algorithm>

const int MAXN = 5e5+5; // 节点数上限

int n, m;
std::vector<int> adj[MAXN]; // 邻接表存图

int dfn[MAXN], low[MAXN], ts; // Tarjan算法所需的时间戳数组
int stk[MAXN], top; // 手动实现的栈，比std::stack稍快
bool isbcc[MAXN]; // 标记节点是否已属于某个v-BCC

std::vector<std::vector<int>> bcc; // 存储所有找到的点双连通分量

void tarjan(int u, int parent) {
    dfn[u] = low[u] = ++ts;
    stk[++top] = u;

    // 对于孤立点，若没有边，则tarjan函数会直接结束。
    // 我们将在main函数中处理这种情况。

    for (int v : adj[u]) {
        // 在无向图中，(u,v)和(v,u)是同一条边，避免访问刚过来的边
        if (v == parent) {
            continue;
        }

        if (!dfn[v]) { // v未被访问，是u在DFS树中的子节点
            tarjan(v, u);
            low[u] = std::min(low[u], low[v]);

            // 关键判断：v及其子树无法到达u的祖先
            if (low[v] >= dfn[u]) {
                std::vector<int> curbcc;
                int node;
                // 从栈中弹出节点，直到v被弹出
                do {
                    node = stk[top--];
                    curbcc.push_back(node);
                    isbcc[node] = true;
                } while (node != v);
                
                // 割点u也属于这个v-BCC
                curbcc.push_back(u);
                isbcc[u] = true;

                bcc.push_back(curbcc);
            }
        } else { // v已被访问，(u,v)是返祖边
            low[u] = std::min(low[u], dfn[v]);
        }
    }
}

int main() {
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(nullptr);

    std::cin >> n >> m;

    for (int i = 0; i < m; ++i) {
        int u, v;
        std::cin >> u >> v;
        // 题目允许重边和自环。对于v-BCC，重边和一条边效果一样，自环可特殊处理
        // 此处我们正常建图，让tarjan处理
        if (u == v) continue; // v-BCC定义通常不考虑自环，但题目样例有，先忽略自环边，最后处理孤立点
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    
    // 遍历所有节点，确保处理完所有连通分量
    for (int i = 1; i <= n; ++i) {
        if (!dfn[i]) {
            // 如果一个节点是孤立的（或只与已访问过的部分相连），
            // tarjan调用后栈可能为空或只含自己。
            // 为了简化，我们只在tarjan内部处理连通的组件。
             tarjan(i, 0);
        }
    }

    // 最后的清扫：处理所有未被分配到任何v-BCC的节点
    // 这些通常是孤立点，或者图中只有一个节点的情况，包括有自环的孤立点
    for (int i = 1; i <= n; ++i) {
        if (!isbcc[i]) {
            bcc.push_back({i});
        }
    }


    // 输出结果
    std::cout << bcc.size() << "\n";
    for (const auto& ret : bcc) {
        std::cout << ret.size();
        for (int node : ret) {
            std::cout << " " << node;
        }
        std::cout << "\n";
    }
}